package ticket;

/**
 * @author DCSGO
 * @version 1.0
 * 编程模拟三个售票窗口
 * 总票数为5，分别使用继承Thread和
 * 实现Runnable的方式模拟，并分析有什么问题
 */
public class SellTicket {
    public static void main1(String[] args) {
        SellTick01 sellTick01 = new SellTick01();
        SellTick01 sellTick02 = new SellTick01();
        SellTick01 sellTick03 = new SellTick01();


        sellTick01.start();
        sellTick02.start();
        sellTick03.start();
        /*
         * 窗口 Thread-0售出1张票 还剩 4张票
         * 窗口 Thread-1售出1张票 还剩 3张票
         * 窗口 Thread-2售出1张票 还剩 2张票
         * 窗口 Thread-1售出1张票 还剩 1张票
         * 窗口 Thread-2售出1张票 还剩 0张票
         * 窗口 Thread-0售出1张票 还剩 1张票
         */
        //虽然在多数情况下售票正常但也有少数情况(如上)下会出现售票数超出预定值
        //且我们不易察觉 原因就在于当剩余票数小于同步执行的到 (--ticketNum)
        //的线程数时就会出现上述情况
    }

    public static void main(String[] args) {
        SellTick02 sellTick02 = new SellTick02();
        new Thread(sellTick02).start();
        new Thread(sellTick02).start();
        new Thread(sellTick02).start();
        /*
         * 窗口 Thread-0售出1张票 还剩 4张票
         * 窗口 Thread-2售出1张票 还剩 2张票
         * 窗口 Thread-1售出1张票 还剩 3张票
         * 窗口 Thread-2售出1张票 还剩 1张票
         * 窗口 Thread-0售出1张票 还剩 0张票
         * 窗口 Thread-1售出1张票 还剩 1张票
         */
        //即使是使用实现 Runnable 接口的方式也无法有效解决收票超过总量的情况
        //原因与上面继承 Thread 相同(在此类情景下 它俩没有太大区别)
    }
}

//继承Thread
class SellTick01 extends Thread {
    private static int ticketNum = 5;

    @Override
    public void run() {
        while (ticketNum > 0) {
            System.out.println("窗口 " + Thread.currentThread().getName()
                    + "售出1张票 还剩 " + (--ticketNum) + "张票");
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

//实现Runnable接口
class SellTick02 implements Runnable {
    //可以仅实例化一个对象并开启多个线程 多个线程操作的是同一个对象
    //故可不用 static 修饰 达到共享的效果
    private int ticketNum = 5;

    @Override
    public void run() {
        while (ticketNum > 0) {
            System.out.println("窗口 " + Thread.currentThread().getName()
                    + "售出1张票 还剩 " + (--ticketNum) + "张票");
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
